<?php
/***********************************************************************
 * @package    IvanEngine
 * @subpackage Core
 * @author     Ivan <ivanzx@msn.com>
 * @created    2010-05-12
 ***********************************************************************/
if(defined("IVANENGINE_CORE_IO_LOG"))
	die("Redefinition macro in :".__FILE__."(".__LINE__.")");
define("IVANENGINE_CORE_IO_LOG", true);

require_once (dirname(__FILE__).'/../Event/Event.php');

class ELogArgs extends CEventArgs
{
    public $message  = '';
    public function __construct($message) 
    {
        parent::__construct ();
        $this->message  = $message;
    }
}

class CLog extends CEvent 
{
    const EVT_FATAL         = 'EVT_FATAL';
    const EVT_ERROR         = 'EVT_ERROR';
    const EVT_WARNING       = 'EVT_WARNING';
    const EVT_NOTE          = 'EVT_NOTE';
    
	const LEVEL_FATAL		= 0;
	const LEVEL_ERROR		= 1;
	const LEVEL_WARING		= 2;
	const LEVEL_NOTE		= 3;
	protected $m_level		= self::LEVEL_NOTE;
	protected $m_msgCountMap= null;
	protected $m_fatalMsg	= null;
	protected $m_errorMsg	= null;
	protected $m_waringMsg	= null;
	protected $m_noteMsg	= null;
    static protected $m_this= null;
    static protected $m_isSingletonNew  = false;
    
	public function __construct() 
	{
		parent::__construct();
        if( self::$m_isSingletonNew == false ){
            throw new CException(get_class($this)." class is singleton object, 
            you can only use CLog::Get() to get it.");
        }
        if( self::$m_this != null ){
            throw new CException("CLog class is singleton object, 
            you can only use CSingleton::Get('CLog') to get it.");
        }
        self::$m_this       = $this;
        
        $this->AddEvent(self::EVT_FATAL);
        $this->AddEvent(self::EVT_ERROR);
        $this->AddEvent(self::EVT_WARNING);
        $this->AddEvent(self::EVT_NOTE);
        
		$this->m_fatalMsg	= new CVector();
		$this->m_errorMsg	= new CVector();
		$this->m_waringMsg	= new CVector();
		$this->m_noteMsg	= new CVector();
		$this->m_msgCountMap= new CVector();
	}
	
	public function __destruct() 
	{
		unset($this->m_fatalMsg);
		unset($this->m_errorMsg);
		unset($this->m_waringMsg);
		unset($this->m_noteMsg);
		unset($this->m_msgCountMap);
		parent::__destruct();
	}
    
    static public function Get()
    {
        if( self::$m_this == null ){
            self::$m_isSingletonNew = true;
            self::$m_this = new CLog();
            self::$m_isSingletonNew = false;
        }
        return self::$m_this;
    }
	
	public function Fatal($message)
	{
		$tempMsg	= "";
		$numargs 	= func_num_args();
		if ($numargs >= 2) {
			$arg_list 	= func_get_args();
			$temp_args	= array();
			for ($i = 1; $i < $numargs; $i++) {
				$temp_args[$i-1] = $arg_list[$i];
	    	}
	    	$tempMsg	= vsprintf($message, $temp_args);
		}else{
			$tempMsg	= $message;
		}
		$this->FireEvent(self::EVT_FATAL, new ELogArgs($message));
		$this->m_msgCountMap->PushBack(self::LEVEL_FATAL);
		$this->m_fatalMsg->PushBack($tempMsg);
	}
	
	public function Error($message)
	{
		$tempMsg	= "";
		$numargs 	= func_num_args();
		if ($numargs >= 2) {
			$arg_list 	= func_get_args();
			$temp_args	= array();
			for ($i = 1; $i < $numargs; $i++) {
				$temp_args[$i-1] = $arg_list[$i];
	    	}
	    	$tempMsg	= vsprintf($message, $temp_args);
		}else{
			$tempMsg	= $message;
		}
		$this->FireEvent(self::EVT_ERROR, new ELogArgs($message));
		$this->m_msgCountMap->PushBack(self::LEVEL_ERROR);
		$this->m_errorMsg->PushBack($tempMsg);
	}
	
	public function Warning($message)
	{
		$tempMsg	= "";
		$numargs 	= func_num_args();
		if ($numargs >= 2) {
			$arg_list 	= func_get_args();
			$temp_args	= array();
			for ($i = 1; $i < $numargs; $i++) {
				$temp_args[$i-1] = $arg_list[$i];
	    	}
	    	$tempMsg	= vsprintf($message, $temp_args);
		}else{
			$tempMsg	= $message;
		}
		$this->FireEvent(self::EVT_WARNING, new ELogArgs($message));
		$this->m_msgCountMap->PushBack(self::LEVEL_WARING);
		$this->m_waringMsg->PushBack($tempMsg);
	}
	
	public function Note($message)
	{
		$tempMsg	= "";
		$numargs 	= func_num_args();
		if ($numargs >= 2) {
			$arg_list 	= func_get_args();
			$temp_args	= array();
			for ($i = 1; $i < $numargs; $i++) {
				$temp_args[$i-1] = $arg_list[$i];
	    	}
	    	$tempMsg	= vsprintf($message, $temp_args);
		}else{
			$tempMsg	= $message;
		}
		$this->FireEvent(self::EVT_NOTE, new ELogArgs($message));
		$this->m_msgCountMap->PushBack(self::LEVEL_NOTE);
		$this->m_noteMsg->PushBack($tempMsg);
	}
	
	public function Level($level = null)
	{
        if( $level === null ){
            return $this->m_level;
        }
		$this->m_level	= $level;
	}
    
    public function Size($level = CLog::LEVEL_NOTE)
    {
        $count  = 0;
        switch($level)
        {
            case self::LEVEL_FATAL:
                $count = $this->m_fatalMsg->Size();
            break;
            case self::LEVEL_ERROR:
                $count = $this->m_fatalMsg->Size();
                $count+= $this->m_errorMsg->Size();
            break;
            case self::LEVEL_WARING:
                $count = $this->m_fatalMsg->Size();
                $count+= $this->m_errorMsg->Size();
                $count+= $this->m_waringMsg->Size();
            break;
            case self::LEVEL_NOTE:
                $count = $this->m_fatalMsg->Size();
                $count+= $this->m_errorMsg->Size();
                $count+= $this->m_waringMsg->Size();
                $count+= $this->m_noteMsg->Size();
            break;
        }
        return $count;
    }
    
    public function Clear($isAll = true, $level = CLog::LEVEL_NOTE)
    {
        if( $isAll ){
            $this->m_fatalMsg->Clear();
            $this->m_errorMsg->Clear();
            $this->m_waringMsg->Clear();
            $this->m_noteMsg->Clear();
            return;
        }
        switch($level)
        {
            case self::LEVEL_FATAL:
                $this->m_fatalMsg->Clear();
            break;
            case self::LEVEL_ERROR:
                $this->m_errorMsg->Clear();
            break;
            case self::LEVEL_WARING:
                $this->m_waringMsg->Clear();
            break;
            case self::LEVEL_NOTE:
                $this->m_noteMsg->Clear();
            break;
        }
    }
    
    public function & GetLog($level)
    {
        switch($level)
        {
            case self::LEVEL_FATAL:
                return $this->m_fatalMsg;
            break;
            case self::LEVEL_ERROR:
                return $this->m_errorMsg;
            break;
            case self::LEVEL_WARING:
                return $this->m_waringMsg;
            break;
            case self::LEVEL_NOTE:
                return $this->m_noteMsg;
            break;
        }
        return null;
    }
	
	public function Message()
	{
		$resultMsg	= "";
		$fatalIt	= $this->m_fatalMsg->Begin();
		$errorIt	= $this->m_errorMsg->Begin();
		$waringIt	= $this->m_waringMsg->Begin();
		$noteIt		= $this->m_noteMsg->Begin();
		for ($i = 0; $i < $this->m_msgCountMap->Size(); $i++)
		{
			$type	= $this->m_msgCountMap->Get($i);
			switch ($type)
			{
				case self::LEVEL_FATAL:
					if( $fatalIt->IsValid() )
						$resultMsg	.= "<span style=\"color:red;\">".$fatalIt->Value()."</span><br>";
					$fatalIt->Next();
					break;
				case self::LEVEL_ERROR:
					if( $this->m_level >= self::LEVEL_ERROR && $errorIt->IsValid() )
						$resultMsg	.= "<span style=\"color:#FF0F87;\">".$errorIt->Value()."</span><br>";
					$errorIt->Next();
					break;
				case self::LEVEL_WARING:
					if( $this->m_level >= self::LEVEL_WARING && $waringIt->IsValid() )
                    {
                        $resultMsg    .= "<span style=\"color:green;\">".$waringIt->Value()."</span><br>";  
                    }
					$waringIt->Next();
					break;
				case self::LEVEL_NOTE:
					if( $this->m_level == self::LEVEL_NOTE && $noteIt->IsValid() )
						$resultMsg	.= "<span>".$noteIt->Value()."</span><br>";
					$noteIt->Next();
					break;
			}
		}
		unset($fatalIt);
		unset($errorIt);
		unset($waringIt);
		unset($noteIt);
		return $resultMsg;
	}
}
?>